#ifndef BASE_THREADPOOL_H
#define BASE_THREADPOOL_H

#include "Singleton.hpp"

#include <vector>
#include <thread>
#include <functional>
#include <future>
#include <atomic>
#include <queue>
#include <condition_variable>

namespace DBServer
{
namespace Base
{
class ThreadPool : public Singleton<ThreadPool> {
friend class Singleton<ThreadPool>;
public:
    typedef std::packaged_task<void(void)> Task;
    void work();
    void stop();
    void commit(std::function<void(void)>);

    // don't allow to be copied
    ~ThreadPool() = default;
    ThreadPool(const ThreadPool&) = delete;
    ThreadPool(const ThreadPool&&) = delete;
    ThreadPool&& operator=(const ThreadPool&&) = delete;
    const ThreadPool& operator=(const ThreadPool&) = delete;
private:
    ThreadPool() = default;
private:
    std::queue<Task>            blocking_queue;     // blocking queue which store the task for thread to execute
    std::mutex                  queue_mut;          // lock the queue tail when the thread put the task
    std::mutex                  queue_get;          // lock the queue head when the thread get the task
    std::atomic_int             is_stop;            // the ThreadPool stops working
    std::vector<std::thread>    pool;               // thread pool
    std::condition_variable     wait;               // the thread wait for this condition_variale to work
};
} // namespace Socket    
} // namespace DBServer



#endif